home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 32 / Mac Magazin and MacEasy Magazine CD - Issue 32.iso / Grafik & Text / Fractal Trees / Sources etc / FractalTreeObject.cpp < prev   
C/C++ Source or Header  |  1997-02-11  |  7KB  |  296 lines

  1. #include <math.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. class FractalTree
  6. {
  7.  
  8.     // TYPE declarations
  9.  
  10.     // The basic tree data type.  consists of branch length, and angle
  11.     // and pointers to the children branches.
  12.     struct TreeType
  13.     {
  14.         float BranchLength;        // Note this is relative length to 1.
  15.                                 // Actual length determined at draw time.
  16.         float BranchAngle;    // in radians
  17.         TreeType *left;
  18.         TreeType *right;
  19.     };
  20.     
  21.     enum SideType {left, right};
  22.  
  23.  
  24.  
  25. //****************************************************************************************
  26. //****************************************************************************************
  27. public:
  28.     // constructor
  29.     FractalTree(int UMaxHeight, float UBranchLengthModifier, 
  30.                             float UBranchAngleModifier, float ULengthRandFactor,
  31.                                 float UAngleRandFactor);
  32.     // creates a memory model of the tree
  33.     void GrowTree();
  34.     // draws the tree to the active window
  35.     void DrawTree();
  36. //****************************************************************************************
  37. //****************************************************************************************    
  38.     
  39.     
  40.     
  41.     
  42. private:
  43.     
  44.     void RecurGrowTree (TreeType *Tree, float BranchLength, float BranchAngle, int curHeight);
  45.     void RecurDrawTree (TreeType *Tree, int x1, int y1, int Level);
  46.  
  47.     int CalculateRootLength();
  48.     float ModifyBranchLength( float BranchLength );
  49.     float ModifyBranchAngle( float BranchAngle, SideType Side );
  50.     void DrawLine( short x1, short y1, short x2, short y2 );    
  51.     float CalculateRandomValue( float RandomValue );
  52.  
  53.     
  54.     TreeType *Root;  // a binary tree to store the Tree data.
  55.     
  56.     int MaxHeight; // the maximum number of sequential branches to add.
  57.     
  58.     float BranchLengthModifier;
  59.     float BranchAngleModifier;
  60.     
  61.     float RootLength;
  62.     
  63.     float LengthRandFactor;
  64.     float AngleRandFactor;
  65.     
  66. };
  67.  
  68.  
  69. // ****************************************************************
  70. // Constructor for FractalTree object.
  71.  
  72. FractalTree :: FractalTree(int UMaxHeight, float UBranchLengthModifier, 
  73.                             float UBranchAngleModifier, float ULengthRandFactor,
  74.                                 float UAngleRandFactor)
  75. {
  76.     // Initialize the tree variables
  77.     
  78.     MaxHeight = UMaxHeight;
  79.     BranchLengthModifier = UBranchLengthModifier;
  80.     BranchAngleModifier = UBranchAngleModifier;
  81.     
  82.     LengthRandFactor = ULengthRandFactor;
  83.     AngleRandFactor = UAngleRandFactor;
  84.     
  85.     // need this for later random calculations
  86.     srand( (unsigned int) time(0) );
  87. }
  88.  
  89.  
  90.  
  91. // GrowTree
  92. // Purpose:  Calls RecurGrowTree with the data in the object.
  93.  
  94. void FractalTree :: GrowTree ()
  95. {
  96.  
  97.     Root = new TreeType;
  98.     
  99.     RecurGrowTree(Root, 1, 3.1415926/2, 0 ); // that's π/2, or 90°.
  100. }
  101.  
  102. // ****************************************************************
  103. // RecurGrowTree for FractalTree object.
  104. // Purpose:  To grow a model of the tree in memory.
  105. //              
  106. // PRE:    The tree is stored in a binary tree, called Root,
  107. //        which already exists and is empty.
  108.  
  109. void FractalTree :: RecurGrowTree (TreeType *Tree, float BranchLength, float BranchAngle,
  110.         int curHeight)
  111. {
  112.     // Variables
  113.     float NewBranchLengthLeft, NewBranchLengthRight;
  114.     float NewBranchAngleLeft, NewBranchAngleRight;
  115.  
  116.     // put the given length and angle into the current branch.
  117.     Tree->BranchLength = BranchLength;
  118.     Tree->BranchAngle = BranchAngle;
  119.     
  120.     // Recursively make the subbranches.
  121.     if (curHeight++ <= MaxHeight)
  122.     {
  123.         
  124.         // prepare to make the children.
  125.  
  126.         // Left child
  127.         Tree->left = new TreeType;
  128.         NewBranchLengthLeft = ModifyBranchLength( BranchLength );
  129.         NewBranchAngleLeft = ModifyBranchAngle( BranchAngle, left );
  130.         RecurGrowTree( Tree->left, NewBranchLengthLeft, NewBranchAngleLeft, curHeight );
  131.         
  132.         // Right child
  133.         Tree->right = new TreeType;
  134.         NewBranchLengthRight = ModifyBranchLength( BranchLength );
  135.         NewBranchAngleRight = ModifyBranchAngle( BranchAngle, right );
  136.         RecurGrowTree( Tree->right, NewBranchLengthRight, NewBranchAngleRight, curHeight );
  137.         
  138.     }
  139.     
  140. }
  141.  
  142.  
  143.  
  144. void FractalTree :: DrawTree ()
  145. {
  146.     // Variables
  147.     int startx;
  148.     int starty;
  149.     
  150.     
  151.     startx = 390;
  152.     starty = 530;
  153.     
  154.     RootLength = 120; // CalculateRootLength();
  155.     
  156.     RecurDrawTree( Root, startx, starty, 0 );
  157. }
  158.  
  159.  
  160.  
  161. void FractalTree :: RecurDrawTree (TreeType *Tree, int x1, int y1, int curHeight)
  162.  
  163. {
  164.     // Variables
  165.     float RealBranchLength;
  166.     
  167.     
  168.     // Calculate x2, y2:
  169.     RealBranchLength = RootLength * Tree->BranchLength;
  170.     int x2 = x1 + RealBranchLength * cos( Tree->BranchAngle );
  171.     int y2 = y1 - RealBranchLength * sin( Tree->BranchAngle );
  172.  
  173.     // Draw the line
  174.     DrawLine( x1, y1, x2, y2 );
  175.     
  176.     if (curHeight++ <= MaxHeight)
  177.     {
  178.         RecurDrawTree(Tree->left, x2, y2, curHeight);
  179.         RecurDrawTree(Tree->right, x2, y2, curHeight);
  180.     }
  181. }
  182.  
  183.  
  184. int FractalTree :: CalculateRootLength()
  185. {
  186.     // Currently do not use width.
  187.     
  188.     // Calculate the RootLength based on the BranchLengthModifier, the height
  189.     // of the window, and the maximum level of the tree.
  190.     // RootLength = Height / ( the sum of the rootlength^i for i = 1 to MaxHeight )
  191.     // This will yield a tree somewhat shorter than the window for all
  192.     // branch angle modifiers not zero.
  193.     
  194.     int temp = 0;
  195.     
  196.     for (int i = 1; i <= MaxHeight; i++)
  197.     {
  198.         temp += pow(BranchLengthModifier, i);
  199.     }
  200.     
  201.     return 200 / temp;  // ********* Need height of the current window!!!!
  202. }
  203.  
  204.  
  205. float FractalTree :: ModifyBranchLength( float BranchLength )
  206. {
  207.     float RandomValue = 0;
  208.     float LengthAddedAtOneStdDev;
  209.     
  210.     // First scale down the branch as required.
  211.     BranchLength = BranchLength * BranchLengthModifier;
  212.     
  213.     
  214.     // calculate the length which would be added to the branch
  215.     // at one standard deviation.
  216.     LengthAddedAtOneStdDev = LengthRandFactor * BranchLength;
  217.     
  218.     // Calculate a random value between -100 and +100.
  219.     RandomValue = CalculateRandomValue(RandomValue);
  220.     
  221.     // Adjust ratios so generated rand value matches with branch length
  222.     RandomValue = RandomValue * (LengthAddedAtOneStdDev/30);    
  223.     // 30 is our arbitrary std. deviation ... we could calculate that better.
  224.     
  225.     
  226.     // adjust branch length
  227.     BranchLength = BranchLength + RandomValue;
  228.     
  229.     
  230.     // Based on BranchLengthModifier, return the new branch length.
  231.     // ie. return BranchLength * BranchLengthModifier.
  232.     
  233.     return BranchLength;
  234. }
  235.  
  236.  
  237. float FractalTree :: CalculateRandomValue( float RandomValue )
  238. {
  239.     float newRand;
  240.     RandomValue = 0;
  241.     
  242.     // set random value to a number between 0 and 200
  243.     for (int i = 1; i <= 20; i++)
  244.     {
  245.         newRand = rand();
  246.         RandomValue = RandomValue + ( (newRand/32768) * 10 );
  247.     }
  248.  
  249.     // set random value to -100 to 100 and return
  250.     return RandomValue - 100;
  251. }
  252.  
  253.  
  254. float FractalTree :: ModifyBranchAngle( float BranchAngle, SideType Side )
  255. {
  256.     float RandomValue = 0;
  257.     float AngleAddedAtOneStdDev;
  258.     
  259.     // Based on BranchAngleModifier return the new branch angle.
  260.     // If left, return BranchAngle + modifier
  261.     // If right, return BranchAngle - modifier.
  262.     // Left and right are determined with the branches rising from the
  263.     // top of the parent.
  264.     
  265.     
  266.     
  267.     
  268.     if (Side == left)
  269.     {
  270.         BranchAngle = BranchAngle + BranchAngleModifier;
  271.     }
  272.     else  // Side = right
  273.     {
  274.         BranchAngle = BranchAngle - BranchAngleModifier;
  275.     }
  276.     
  277.     AngleAddedAtOneStdDev = AngleRandFactor * BranchAngleModifier;
  278.     
  279.     RandomValue = CalculateRandomValue(RandomValue);
  280.     
  281.     RandomValue = RandomValue * AngleAddedAtOneStdDev / 20;
  282.     
  283.     
  284.     return BranchAngle + RandomValue;
  285. }
  286.  
  287.  
  288. // ****************************************************************
  289. // DrawLine
  290.  
  291. void FractalTree :: DrawLine( short x1, short y1, short x2, short y2 )
  292. {
  293.     MoveTo( x1, y1 );
  294.     LineTo( x2, y2 );
  295. }
  296.